package com.gzhryc.shared_device.cdb.code;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.cdb.code.dao.db.BatteryCabinet;
import com.gzhryc.shared_device.cdb.code.dao.db.BatteryCabinetSlot;
import com.gzhryc.shared_device.cdb.code.dao.db.CDBOrder;
import com.gzhryc.shared_device.cdb.code.dao.db.PortableBattery;
import com.gzhryc.shared_device.cdb.code.dao.enums.BatteryCabinetEnum;
import com.gzhryc.shared_device.cdb.code.dao.enums.CDBOrderEnum;
import com.gzhryc.shared_device.cdb.code.dao.enums.PortableBatteryEnum;
import com.gzhryc.shared_device.cdb.code.services.BatteryCabinetService;
import com.gzhryc.shared_device.cdb.code.services.BatteryCabinetSlotService;
import com.gzhryc.shared_device.cdb.code.services.CDBOrderService;
import com.gzhryc.shared_device.cdb.code.services.PortableBatteryService;
import com.gzhryc.shared_device.cdb.code.services.models.CDBForceEjectSlotCacheData;
import com.gzhryc.shared_device.cdb.core.ICDBNetworkEventListener;
import com.gzhryc.shared_device.cdb.core.enums.ECDBLeaseResultCode;
import com.gzhryc.shared_device.cdb.core.models.CDBEjectResult;
import com.gzhryc.shared_device.cdb.core.models.CDBLeaseResult;
import com.gzhryc.shared_device.cdb.core.models.CDBReturnNotify;
import com.gzhryc.shared_device.cdb.core.models.CDBSearchResult;
import com.gzhryc.shared_device.iot.code.IIOTLogServer;

import java.util.Date;
import java.util.List;

public class CDBNetworkEventListener implements ICDBNetworkEventListener {

    static Logger log = Logger.getLogger(CDBNetworkEventListener.class);

    private final String jdbcKey;
    private final OperateInfo operateInfo;
    private final IIOTLogServer iotLogServer;
    private final ICDBBusinessEventListener businessEventListener;
    private final ICDBCacheManager cacheManager;

    public CDBNetworkEventListener(String jdbcKey,IIOTLogServer iotLogServer, ICDBBusinessEventListener businessEventListener,
                                   ICDBCacheManager cacheManager, OperateInfo operateInfo){
        this.jdbcKey = jdbcKey;
        this.iotLogServer = iotLogServer;
        this.businessEventListener = businessEventListener;
        this.cacheManager = cacheManager;
        this.operateInfo = ClassTools.copy(new OperateInfo(),operateInfo);
        this.operateInfo.setOperator("共享充电宝网络事件监听程序");
    }

    @Override
    public void leaseReceiveHandle(CDBLeaseResult leaseResult) {
        log.info("充电宝租借结果返回：{{0:json}}",leaseResult);
        CDBWorkCacheManager.DeviceWorkInfo deviceWorkInfo = CDBWorkCacheManager.self().getAndRemoveData(leaseResult.getDeviceSn(),leaseResult.getMsgId());
        if(deviceWorkInfo == null){
            deviceWorkInfo = new CDBWorkCacheManager.DeviceWorkInfo();
            deviceWorkInfo.setDeviceSn(leaseResult.getDeviceSn());
            deviceWorkInfo.setTradeNo(leaseResult.getTradeNo());
            deviceWorkInfo.setSlotNum(leaseResult.getSlotNum());
        }

        CDBOrder cdbOrder = CDBOrderService.self(new Date()).getByTradeNo(deviceWorkInfo.getTradeNo());
        if(cdbOrder != null){
            if(CDBOrderEnum.State.Opening.index().equals(cdbOrder.getState())) {
                cdbOrder.setLeasePower(leaseResult.getPower());
                cdbOrder.setPortableBatterySn(leaseResult.getPortableBatterySn());
                cdbOrder.setLeaseSlotNum(leaseResult.getSlotNum());

                if (ECDBLeaseResultCode.Success.index().equals(leaseResult.getResultCode())) {
                    operateInfo.setOperateNote("租借充电宝租借成功通知");
                    CDBOrderService.self(cdbOrder.getCreateDate()).openingSuccess(cdbOrder, operateInfo);
                    if (!PortableBatteryService.self().eject(leaseResult.getPortableBatterySn(), cdbOrder.getTradeNo())) {
                        log.error("致命错误，修改充电宝租借信息错误，充电宝ID：{{0}}", leaseResult.getPortableBatterySn());
                    }
                    //清理缓存
                    cacheManager.removeBatteryCabinetSlot(leaseResult.getDeviceSn(),leaseResult.getSlotNum());
                } else {
                    operateInfo.setOperateNote(ECDBLeaseResultCode.note(leaseResult.getResultCode()));
                    Integer leaseErrorState = CDBOrderEnum.LeaseErrorState.NoPortableBattery.index();
                    if(ECDBLeaseResultCode.NotRemoved.index().equals(leaseResult.getResultCode())){
                        leaseErrorState = CDBOrderEnum.LeaseErrorState.NotRemoved.index();
                    }else if(ECDBLeaseResultCode.LockException.index().equals(leaseResult.getResultCode())){
                        leaseErrorState = CDBOrderEnum.LeaseErrorState.LockException.index();
                    }else if(ECDBLeaseResultCode.Overtime.index().equals(leaseResult.getResultCode())){
                        leaseErrorState = CDBOrderEnum.LeaseErrorState.Timeout.index();
                    }
                    CDBOrderService.self(cdbOrder.getCreateDate()).openingFail(cdbOrder, leaseErrorState,operateInfo);
                }
                businessEventListener.leaseResult(cdbOrder, leaseResult);
            }else{
                log.error("租借返回时，设备订单状态不对，订单号：{{0}}，订单状态：{{1}}",cdbOrder.getTradeNo(),cdbOrder.getStateName()+"("+cdbOrder.getState()+")");
            }
        }else {
            if(ECDBLeaseResultCode.Success.index().equals(leaseResult.getResultCode())) {
                if (!PortableBatteryService.self().eject(leaseResult.getPortableBatterySn(), leaseResult.getTradeNo())) {
                    log.error("致命错误，修改充电宝租借信息错误，充电宝ID：{{0}}", leaseResult.getPortableBatterySn());
                }
                //清理缓存
                cacheManager.removeBatteryCabinetSlot(leaseResult.getDeviceSn(),leaseResult.getSlotNum());
            }
            log.error("租借返回时，未找到设备订单，返回内容：{{0:json}}",leaseResult);
        }
    }

    @Override
    public void searchResultHandle(CDBSearchResult searchResult) {
        //log.info("共享充电宝设备查询，内容：{{0:json}}", searchResult);
        MultiDBTools.setJdbcKey(jdbcKey);
        try {
            BatteryCabinet batteryCabinet = cacheManager.getBatteryCabinet(searchResult.getDeviceSn());
            if(batteryCabinet == null) {
                batteryCabinet = BatteryCabinetService.self().getByDeviceSn(searchResult.getDeviceSn());
                if (batteryCabinet != null) {
                    BatteryCabinetService.self().online(batteryCabinet.getDeviceSn(), searchResult.getVersionNumber(), searchResult.getImsi()
                            , searchResult.getIccid(), searchResult.getRssi());
                    batteryCabinet.setState(BatteryCabinetEnum.State.Online.index());
                    batteryCabinet.setHeartbeatData(new Date());
                    cacheManager.saveBatteryCabinet(batteryCabinet);
                }
            }

            if (batteryCabinet != null) {
                for (Integer slotNum = 1; slotNum <= batteryCabinet.getSlotTotal(); slotNum++) {
                    CDBSearchResult.SlotItem slotItem = null;
                    if (searchResult.getItems() != null && searchResult.getItems().size() > 0) {
                        for (CDBSearchResult.SlotItem item : searchResult.getItems()) {
                            if (item.getSlotNum().equals(slotNum)) {
                                slotItem = item;
                                break;
                            }
                        }
                    }
                    BatteryCabinetSlot batteryCabinetSlot = BatteryCabinetSlotService.self().getOrAddByKeys(searchResult.getDeviceSn(), slotNum);
                    if (batteryCabinetSlot == null) {
                        log.error("共享充电宝设备查询，获取或新增卡槽信息失败，设备序列号：{{0}}，卡槽：{{1}}", searchResult, slotNum);
                        continue;
                    }

                    if (slotItem != null) {
                        if (StringTools.isNotBlank(slotItem.getSubDeviceSn())) {
                            //查询结果与数据库保存的充电宝不一致
                            if (StringTools.isBlank(batteryCabinetSlot.getPortableBatterySn()) ||
                                    !batteryCabinetSlot.getPortableBatterySn().equals(slotItem.getSubDeviceSn())) {
                                batteryCabinetSlot.setPortableBatterySn(slotItem.getSubDeviceSn());
                                if (!BatteryCabinetSlotService.self().updateNotNull(batteryCabinetSlot)) {
                                    log.error("共享充电宝设备查询，修改槽信息失败，设备序列号：{{0}}，卡槽：{{1}}", searchResult, slotNum);
                                }
                            }

                            PortableBattery portableBattery = PortableBatteryService.self().getByDeviceSn(slotItem.getSubDeviceSn());
                            if (portableBattery == null) {
                                portableBattery = new PortableBattery();
                                portableBattery.setDeviceSn(slotItem.getSubDeviceSn());
                                portableBattery.setPower(slotItem.getPower());
                                portableBattery.setCabinetDeviceSn(searchResult.getDeviceSn());
                                portableBattery.setSlotNum(slotNum);
                                portableBattery.setState(PortableBatteryEnum.State.Charging.index());
                                portableBattery.setLastHeartDate(new Date());
                                if (!PortableBatteryService.self().add(portableBattery)) {
                                    log.error("共享充电宝设备查询，新增充电宝失败，设备序列号：{{0}}，卡槽：{{1}}，充电宝ID：{{2}}", searchResult, slotNum, slotItem.getSubDeviceSn());
                                }
                            } else {
                                //检查是否需要更新
                                boolean flag = false;
                                if (StringTools.isBlank(portableBattery.getCabinetDeviceSn())
                                        || !portableBattery.getCabinetDeviceSn().equals(batteryCabinet.getDeviceSn())) {
                                    flag = true;
                                }
                                if (!flag && !portableBattery.getSlotNum().equals(slotItem.getSlotNum())) {
                                    flag = true;
                                }
                                if (!flag && portableBattery.getPower() == null && !portableBattery.getPower().equals(slotItem.getPower())) {
                                    flag = true;
                                }
                                if (!flag && !PortableBatteryEnum.State.Charging.index().equals(portableBattery.getState())) {
                                    flag = true;
                                }

                                if (flag) {
                                    if (!PortableBatteryService.self().revert(portableBattery.getDeviceSn(), batteryCabinet.getDeviceSn()
                                            , slotItem.getSlotNum(), slotItem.getPower())) {
                                        log.error("查询共享充电宝时，更新充电宝信息失败，充电宝ID：{{0}}", portableBattery.getDeviceSn());
                                    }
                                }
                            }
                            batteryCabinetSlot.setPortableBattery(portableBattery);
                        } else if (StringTools.isNotBlank(batteryCabinetSlot.getPortableBatterySn())) {
                            if (!BatteryCabinetSlotService.self().removePortableBatterySn(searchResult.getDeviceSn(), slotNum)) {
                                log.error("共享充电宝设备查询，移除卡槽中充电宝失败，设备序列号：{{0}}，卡槽：{{1}}，充电宝ID：{{2}}", searchResult, slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                            if (!PortableBatteryService.self().eject(batteryCabinetSlot.getPortableBatterySn())) {
                                log.error("共享充电宝设备查询，修改充电宝弹出失败，设备序列号：{{0}}，卡槽：{{1}}，充电宝ID：{{2}}", searchResult, slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                            batteryCabinetSlot.setPortableBatterySn(null);
                        }
                        cacheManager.saveBatteryCabinetSlot(batteryCabinetSlot);
                    } else {
                        if (StringTools.isNotBlank(batteryCabinetSlot.getPortableBatterySn())) {
                            if (!BatteryCabinetSlotService.self().removePortableBatterySn(searchResult.getDeviceSn(), slotNum)) {
                                log.error("共享充电宝设备查询，移除卡槽中充电宝失败，设备序列号：{{0}}，卡槽：{{1}}，充电宝ID：{{2}}", searchResult, slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                            if (!PortableBatteryService.self().eject(batteryCabinetSlot.getPortableBatterySn())) {
                                log.error("共享充电宝设备查询，修改充电宝弹出失败，设备序列号：{{0}}，卡槽：{{1}}，充电宝ID：{{2}}", searchResult, slotNum, batteryCabinetSlot.getPortableBatterySn());
                            }
                        }
                        cacheManager.removeBatteryCabinetSlot(searchResult.getDeviceSn(), batteryCabinetSlot.getSlotNum());
                    }
                }
            } else {
                log.error("共享充电宝设备查询结果，未找到设备信息，报文：{{0:json}}", searchResult);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            JdbcSession.clear();
            MultiDBTools.removeJdbcKey();
        }
    }

    @Override
    public void ejectReceiveHandle(CDBEjectResult ejectResponse) {
        log.info("充电宝弹出结果返回：{{0:json}}",ejectResponse);
        if (ECDBLeaseResultCode.Success.index().equals(ejectResponse.getResultCode())) {
            CDBForceEjectSlotCacheData ejectSlotCacheData =  cacheManager.getCommandResult(ejectResponse.getDeviceSn(),ejectResponse.getMsgId(), CDBForceEjectSlotCacheData.class);
            if(ejectSlotCacheData != null){
                log.info("获取命令缓存：{{0:json}}",ejectSlotCacheData);
                if(ejectSlotCacheData.getSlotNum() == null || ejectSlotCacheData.getSlotNum() == 0){
                    //全部弹出
                    cacheManager.removeBatteryCabinetSlot(ejectSlotCacheData.getDeviceSn());
                    List<BatteryCabinetSlot> batteryCabinetSlotList = BatteryCabinetSlotService.self().findJoinByDeviceSn(ejectSlotCacheData.getDeviceSn());
                    if(batteryCabinetSlotList != null && batteryCabinetSlotList.size() > 0){
                        for(BatteryCabinetSlot slot : batteryCabinetSlotList){
                            if(StringTools.isNotBlank(slot.getPortableBatterySn())) {
                                if (!PortableBatteryService.self().eject(slot.getPortableBatterySn(), null)) {
                                    log.error("致命错误，修改充电宝租借信息错误，充电宝ID：{{0}}", slot.getPortableBatterySn());
                                }
                            }
                        }
                    }
                }else {
                    BatteryCabinetSlot slot = BatteryCabinetSlotService.self().getOrAddByKeys(ejectSlotCacheData.getDeviceSn(), ejectSlotCacheData.getSlotNum());
                    if (slot != null && StringTools.isNotBlank(slot.getPortableBatterySn())) {
                        //清理缓存
                        cacheManager.removeBatteryCabinetSlot(slot.getDeviceSn(),slot.getSlotNum());
                        if (!PortableBatteryService.self().eject(slot.getPortableBatterySn(), null)) {
                            log.error("致命错误，修改充电宝租借信息错误，充电宝ID：{{0}}", slot.getPortableBatterySn());
                        }
                    }
                }
            }
        }
    }

    @Override
    public void returnHandle(CDBReturnNotify returnNotify) {
        log.info("充电宝归还通知：{{0:json}}",returnNotify);
        PortableBattery portableBattery = PortableBatteryService.self().getByDeviceSn(returnNotify.getPortableBatterySn());
        if(portableBattery == null){
            //不存在的充电宝ID
            portableBattery = new PortableBattery();
            portableBattery.setDeviceSn(returnNotify.getPortableBatterySn());
            portableBattery.setCabinetDeviceSn(returnNotify.getDeviceSn());
            if(!PortableBatteryService.self().add(portableBattery)){
                log.error("未知的充电宝ID，新增失败，归还信息：{{0:json}}",returnNotify);
                return;
            }

        }
        if(!PortableBatteryService.self().revert(returnNotify.getPortableBatterySn(),returnNotify.getDeviceSn()
                ,returnNotify.getSlotNum(),returnNotify.getPower())){
            log.error("致命错误，修改充电宝归还信息失败，充电宝ID：{{0}}",returnNotify.getPortableBatterySn());
        }
        if(StringTools.isNotBlank(portableBattery.getCurrentTradeNo())){
            CDBOrder cdbOrder = CDBOrderService.self(new Date()).getByTradeNo(portableBattery.getCurrentTradeNo());
            if(cdbOrder != null){
                if(!CDBOrderEnum.State.RevertFinish.index().equals(cdbOrder.getState())){
                    businessEventListener.revertResult(cdbOrder,portableBattery,returnNotify,operateInfo);
                }
            }
        }
    }

    @Override
    public void heart(String deviceSn, String versionNumber, String imsi, String iccid, Integer rssi) {
        BatteryCabinet batteryCabinet = cacheManager.getBatteryCabinet(deviceSn);
        if(batteryCabinet == null){
            batteryCabinet = BatteryCabinetService.self().getByDeviceSn(deviceSn);
            if (batteryCabinet != null) {
                BatteryCabinetService.self().online(batteryCabinet.getDeviceSn(),versionNumber,imsi,iccid,rssi);
                batteryCabinet.setState(BatteryCabinetEnum.State.Online.index());
                batteryCabinet.setHeartbeatData(new Date());
                cacheManager.saveBatteryCabinet(batteryCabinet);
            }
        }
    }

    @Override
    public void online(String deviceSn, String versionNumber, String imsi, String iccid, Integer rssi) {
        BatteryCabinet batteryCabinet = BatteryCabinetService.self().getByDeviceSn(deviceSn);
        if (batteryCabinet != null) {
            BatteryCabinetService.self().online(batteryCabinet.getDeviceSn(),versionNumber,imsi,iccid,rssi);
            batteryCabinet.setState(BatteryCabinetEnum.State.Online.index());
            batteryCabinet.setHeartbeatData(new Date());
            cacheManager.saveBatteryCabinet(batteryCabinet);
        }
    }

    @Override
    public void offline(String deviceSn) {
        BatteryCabinetService.self().offline(deviceSn);
        cacheManager.removeBatteryCabinet(deviceSn);
    }
}
